/**
 * Copyright (c) 2017, Alex. All rights reserved.
 */
package com.oschina.bottle.common.model;

import com.oschina.bottle.common.dto.BaseDTO;
import com.oschina.bottle.common.constants.Constant;
import com.oschina.bottle.common.enums.CodeEnum;
import com.oschina.bottle.common.enums.MsgEnum;
import com.oschina.bottle.common.enums.RtnCodeEnum;
import com.oschina.bottle.common.exception.BaseException;
import com.oschina.bottle.common.exception.ErrorCodeException;

/**
 * 契约类
 * 可以前后端数据传输标准 服务之间数据传输标准
 * ++++ 支持CodeEnum、MsgEnum的转换
 * ++++ 支持EaseException、ErrorCodeException的转换
 *
 * @author <a href="mailto:zhongchao@gegejia.com">zhong</a>
 * @version 1.0 2017/9/27
 * @since 1.0
 */
public class Result<T> extends BaseDTO {

    private Long code;

    private String msg;

    private T data;

    public Long getCode() {
        return code;
    }

    public String getMsg() {
        return msg;
    }

    public T getData() {
        return data;
    }

    /**
     * 返回一个success结果
     */
    public static Result success() {
        return build(RtnCodeEnum.SUCCESS);
    }

    /**
     * 返回一个success结果 包含data
     */
    public static <T> Result<T> success(T data) {
        Result<T> result = success();
        result.data = data;
        return result;
    }


    public static Result fail(CodeEnum codeEnum) {
        return build(codeEnum);
    }

    public static Result fail(String msg) {
        return fail(Constant.UNKNOWN_ERROR, msg);
    }

    public static Result fail(long code, String msg) {
        return build(code, msg);
    }

    /**
     * 异常转换为Result
     */
    public static Result fail(Exception ex) {
        if (ex instanceof ErrorCodeException) {
            return fail(((ErrorCodeException) ex).getCode(), ex.getMessage());
        } else if (ex instanceof BaseException) {
            return fail(ex.getMessage());
        } else {
            return fail(Constant.UNKNOWN_ERROR, "服务器发生未知异常");
        }
    }

    private static Result build(CodeEnum codeEnum) {
        String msg = null;
        if (codeEnum instanceof MsgEnum) {
            msg = ((MsgEnum) codeEnum).getMsg();
        }

        Long code;
        Object obj = codeEnum.getCode();
        if (obj instanceof Long || obj instanceof Integer || obj instanceof Short || obj instanceof Byte) {
            code = (Long) obj;
        } else if (obj instanceof String) {
            code = Long.parseLong(obj.toString());
        } else {
            throw new IllegalArgumentException("this code must be Long, Integer, Short, Byte, Long");
        }

        return build(code, msg);
    }

    private static Result build(long code, String msg) {
        Result result = new Result();
        result.code = code;
        result.msg = msg;
        return result;
    }
}
